package com.csx.base.design.constructor.singleton;

/**
 * 集群环境下的单例
 * 实现思路：
 *      我们需要把这个单例对象序列化并存储到外部共享存储区(比如文件)，进程在使用这个单例对象时，需要从外部共享存储区
 *      读到内存，并反序列化成对象，然后再使用，使用完毕之后再存储回外部共享存储区
 * @author cuisongxu
 * @date 2023/3/27 18:23
 */
public class IdGenerator {

    private static IdGenerator instance;

    private static SharedObjectStorage storage = new FileSharedObjectStorage("/文件地址");

    private static DistributedLock lock = new DistributedLock();

    /**
     * 私有化构造器
     */
    private IdGenerator() {}

    public synchronized static IdGenerator getInstance() {
        if(instance == null) {
            lock.lock();
            instance = storage.load(IdGenerator.class);
        }
        return instance;
    }

    public synchronized void freeInstance() {
        storage.save(this, IdGenerator.class);
        // 释放对象
        instance = null;
        lock.unlock();
    }


    interface SharedObjectStorage {

        /**
         * 根据clazz从存储中加载并反序列化，返回该对象
         * @param clazz
         * @param <T>
         * @return
         */
        <T> T load(Class<T> clazz);

        /**
         * 序列化对象，保存在外部存储中
         * @param obj 保存的对象
         * @param clazz
         * @param <T>
         */
        <T> void save(T obj, Class<T> clazz);
    }

    static class FileSharedObjectStorage implements SharedObjectStorage {

        private final String filePath;

        public FileSharedObjectStorage(String filePath) {
            this.filePath = filePath;
        }

        @Override
        public <T> T load(Class<T> clazz) {
            // 从文件夹系统中加载并反序列化该类，返回实例对象
            return null;
        }

        @Override
        public <T> void save(T obj, Class<T> clazz) {
            // 序列化对象到文件系统
        }
    }

    /**
     * 分布式锁
     */
    static class DistributedLock {

        void lock() {
            // 分布式锁加锁操作
        }

        void unlock() {
            // 分布式锁解锁操作
        }

    }
}
